/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MainGui.java
 *
 * Created on Apr 2, 2011, 3:40:13 PM
 */

package gui;

import util.Equation;
import util.Molecule;
import util.Periodic;
import util.Stoichiometry;
import util.exceptions.FOCException;
import util.exceptions.UnbalancableEquationException;
import util.exceptions.UnknownElementException;

import javax.swing.*;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * @author Donald Scott
 */
public class MainGui extends javax.swing.JFrame {
    /**
     * For serialization.
     */
    private static final long serialVersionUID = 1L;
    private JPanel StoiCalcPanel = new JPanel();
    Equation equation;
    MoleculeImageCenter images;
    /**
     * Creates new form MainGui
     */
    public MainGui() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
       
		this.setIconImage(new ImageIcon("trunk\\gui\\icon.png").getImage());
		
        initComponents();
        StoiCalcPanel.setLayout(new BoxLayout(StoiCalcPanel, BoxLayout.PAGE_AXIS));
        StoiCalcPane.getViewport().add(StoiCalcPanel);
        StoiCalcPanel.setVisible(true);


        this.setSize(new Dimension(430,500));
        setVisible(true);
        loadTable();
        images = new MoleculeImageCenter();
        FOCException.setFrame(this);
    }

    public static void loadTable() {
        long time = System.nanoTime();
        Periodic.initialize();
        long end = System.nanoTime();
        System.out.println("Memory loadtime: " + (end - time) / 1000000.0 + " milliseconds");  //1 nanosecond = 1.0 � 10-6 milliseconds
    }

    public static void setLookandFeel() {
        try {
            // Set System L&F
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            
        } catch (UnsupportedLookAndFeelException e) {
            // handle exception
        } catch (ClassNotFoundException e) {
            // handle exception
        } catch (InstantiationException e) {
            // handle exception
        } catch (IllegalAccessException e) {
            // handle exception
        }

    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel1 = new javax.swing.JPanel();
        leftEquationField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        rightEquationField = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        equationPanel = new javax.swing.JPanel();
        equationLabel = new gui.EquationLabel();
        StoiPanel = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        dataList = new javax.swing.JList(new DefaultListModel());
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        addValField = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        unitBox = new javax.swing.JComboBox();
        jLabel4 = new javax.swing.JLabel();
        prefixBox = new javax.swing.JComboBox();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        moleculeField = new javax.swing.JComboBox();
        jLabel7 = new javax.swing.JLabel();
        LimitingLabel = new javax.swing.JLabel();
        StoiResultsPanel = new javax.swing.JPanel();
        StoiCalcPane = new javax.swing.JScrollPane();
        statusText = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("FOC Equation Solver");
        setResizable(false);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Equation"));

        jLabel1.setText("=>");

        jButton1.setText("Balance");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BalanceButtonHandler(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(leftEquationField, javax.swing.GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rightEquationField, javax.swing.GroupLayout.DEFAULT_SIZE, 177, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(leftEquationField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(rightEquationField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addContainerGap(13, Short.MAX_VALUE))
        );

        equationPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Balanced Equation"));

        equationLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        equationLabel.setText("Waiting for Input");

        javax.swing.GroupLayout equationPanelLayout = new javax.swing.GroupLayout(equationPanel);
        equationPanel.setLayout(equationPanelLayout);
        equationPanelLayout.setHorizontalGroup(
            equationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(equationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 398, Short.MAX_VALUE)
        );
        equationPanelLayout.setVerticalGroup(
            equationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(equationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
        );

        StoiPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Stoichiometric Data"));

        jLabel2.setFont(new java.awt.Font("Tahoma", 2, 11));
        jLabel2.setText("Imput data relating to your scenario. ");

        jScrollPane1.setViewportView(dataList);

        jButton3.setText("Remove");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RemoveButtonHandle(evt);
            }
        });

        jButton4.setText("Add");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                AddButtonHandler(evt);
            }
        });

        addValField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                StoiAddFieldKeyPress(evt);
            }
        });

        jLabel3.setFont(new java.awt.Font("Tahoma", 2, 11));
        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText("value");

        unitBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "(g)mass", "(L)volume", "mol" }));

        jLabel4.setFont(new java.awt.Font("Tahoma", 2, 11));
        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel4.setText("unit type");

        prefixBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "giga", "mega", "kilo", "hecto", "deca", "BASE", "deci", "centi", "milli", "micro", "nano", "pico", " " }));

        jLabel5.setFont(new java.awt.Font("Tahoma", 2, 11));
        jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel5.setText("prefix");

        jLabel6.setFont(new java.awt.Font("Tahoma", 2, 11));
        jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel6.setText("molecule");

        moleculeField.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));

        jLabel7.setText("Limiting Reactant:");

        LimitingLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
        LimitingLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        LimitingLabel.setText("none");

        javax.swing.GroupLayout StoiPanelLayout = new javax.swing.GroupLayout(StoiPanel);
        StoiPanel.setLayout(StoiPanelLayout);
        StoiPanelLayout.setHorizontalGroup(
            StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(StoiPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, StoiPanelLayout.createSequentialGroup()
                        .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 285, Short.MAX_VALUE)
                            .addGroup(StoiPanelLayout.createSequentialGroup()
                                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
                                    .addComponent(moleculeField, 0, 64, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(addValField, javax.swing.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(prefixBox, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(unitBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(jLabel4))))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jButton3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE)
                            .addComponent(jButton4, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE)
                            .addComponent(jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE)
                            .addComponent(LimitingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE)))
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE))
                .addContainerGap())
        );
        StoiPanelLayout.setVerticalGroup(
            StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, StoiPanelLayout.createSequentialGroup()
                .addComponent(jLabel2)
                .addGap(6, 6, 6)
                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jButton4)
                    .addGroup(StoiPanelLayout.createSequentialGroup()
                        .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel4)
                            .addComponent(jLabel5)
                            .addComponent(jLabel3)
                            .addComponent(jLabel6))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(unitBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(addValField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(prefixBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(moleculeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(StoiPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(StoiPanelLayout.createSequentialGroup()
                        .addComponent(jButton3)
                        .addGap(30, 30, 30)
                        .addComponent(jLabel7)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(LimitingLabel)
                        .addGap(54, 54, 54))
                    .addGroup(StoiPanelLayout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())))
        );

        StoiResultsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Stoichiometric Calculations"));

        StoiCalcPane.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));

        javax.swing.GroupLayout StoiResultsPanelLayout = new javax.swing.GroupLayout(StoiResultsPanel);
        StoiResultsPanel.setLayout(StoiResultsPanelLayout);
        StoiResultsPanelLayout.setHorizontalGroup(
            StoiResultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(StoiResultsPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(StoiCalcPane, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)
                .addContainerGap())
        );
        StoiResultsPanelLayout.setVerticalGroup(
            StoiResultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(StoiResultsPanelLayout.createSequentialGroup()
                .addComponent(StoiCalcPane, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
                .addContainerGap())
        );

        statusText.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        jMenu1.setText("File");

        jMenuItem1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/exit.png"))); // NOI18N
        jMenuItem1.setText("Exit");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitHandle(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuBar1.add(jMenu1);

        jMenu3.setText("About");

        jMenuItem2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/small_info_icon.png"))); // NOI18N
        jMenuItem2.setText("About");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                AboutHandle(evt);
            }
        });
        jMenu3.add(jMenuItem2);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(equationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addComponent(StoiPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(StoiResultsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(statusText, javax.swing.GroupLayout.PREFERRED_SIZE, 118, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(156, 156, 156)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(equationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(StoiPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 229, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(StoiResultsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(18, 18, 18)
                .addComponent(statusText))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void BalanceButtonHandler(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BalanceButtonHandler

        formatEquationField(leftEquationField);
        formatEquationField(rightEquationField);
        try {
            setEquation(leftEquationField.getText(), rightEquationField.getText());
            equationLabel.setEquation(equation.toFormattedString());
            moleculeField.removeAllItems();
            for (Molecule mol : equation.getMolecules()) {
                moleculeField.addItem(mol);
            }
            prefixBox.setSelectedIndex(5);

            equationPanel.setVisible(true);
            StoiPanel.setVisible(true);
            StoiResultsPanel.setVisible(true);
            StoiCalcPanel.removeAll();
            ((DefaultListModel) dataList.getModel()).removeAllElements();
            equationLabel.repaint();
        } catch (FOCException e) {
            e.showMessageDialog();
        }

    }//GEN-LAST:event_BalanceButtonHandler

    private void StoiAddFieldKeyPress(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_StoiAddFieldKeyPress
        String text = addValField.getText();
        if (text.length() == 0)
            return;
        if (!isNumber("" + text.charAt(text.length() - 1)) && text.charAt(text.length() - 1) != '.') {
            addValField.setText(text.substring(0, text.length() - 1));

        }
    }//GEN-LAST:event_StoiAddFieldKeyPress

    private void AddButtonHandler(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AddButtonHandler
        if (!addValField.getText().equals("") && moleculeField.getItemCount() != 0) {
            ((DefaultListModel) dataList.getModel()).addElement(new StoiData(moleculeField.getSelectedItem().toString(), Double.parseDouble(addValField.getText()), (String) prefixBox.getSelectedItem(), (String) unitBox.getSelectedItem()));
            moleculeField.removeItem(moleculeField.getSelectedItem());
            //TODO Calculate if the user entered both reactants, signaling a limiting-reactants problem.

            calcValues();
        }
    }//GEN-LAST:event_AddButtonHandler

    private void calcValues() {
        this.setSize(new Dimension(785, 500));
        this.validate();
        this.validateTree();
        List<StoiData> rules = new ArrayList<StoiData>();
        for (Object rule : (((DefaultListModel) dataList.getModel()).toArray())) {
            rules.add((StoiData) rule);
        }
        if (rules.size() == 0) {
            LimitingLabel.setText("none");
            StoiCalcPanel.removeAll();
            return;
        }
        //IF THERE ARE NO ELEMENTS, NO CODE WILL BE EXECUTED BELOW THIS!
        Stoichiometry stoi = new Stoichiometry(equation);

        //Add rules
        for (StoiData sd : rules) {
            try {
                stoi.add(sd);
            } catch (UnknownElementException e) {
                e.showMessageDialog();
            }
        }
        //Set limiting
        String limiting = stoi.getLimiting();
        if (limiting != null)
            LimitingLabel.setText(limiting);
        else
            LimitingLabel.setText("none");
        StoiCalcPanel.removeAll();
        for (Molecule mol : equation.getMolecules()) {
            StoiPanel panel = new StoiPanel(mol.toString(), stoi.getResult(mol, 'm'), stoi.getResult(mol, 'g'), stoi.getResult(mol, 'l'));
            MoleculeImageCenter.populateImagePanel(panel, mol);
            StoiCalcPanel.add(panel);
        }
        StoiCalcPanel.revalidate();
        StoiCalcPane.getViewport().validate();
        StoiCalcPane.validate();
        this.validate();
        this.validateTree();
    }


    private void ExitHandle(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ExitHandle
        System.exit(0);
    }//GEN-LAST:event_ExitHandle

    private void RemoveButtonHandle(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RemoveButtonHandle
        int index = dataList.getSelectedIndex();
        if (index >= 0) {
            int curIndex = dataList.getSelectedIndex();
            DefaultListModel dlm = ((DefaultListModel) dataList.getModel());
            StoiData c = (StoiData) dlm.getElementAt(index);
            try {
                moleculeField.addItem(new Molecule(c.getMolecule()));
            } catch (UnknownElementException e) {
                e.printStackTrace();
            }
            dlm.removeElementAt(index);
            if (((DefaultListModel) dataList.getModel()).getSize() > 0) {
                if (curIndex <= 0)
                    curIndex++;
                dataList.setSelectedIndex(curIndex - 1);
            }
        }
        calcValues();
    }//GEN-LAST:event_RemoveButtonHandle

    private void AboutHandle(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AboutHandle
        JOptionPane.showMessageDialog(this,
                     "FOC Chemical Equation Calculator\n(C) 2011 - All rights Reserved \n\nCredits:\nIdea, GUI and Stoichiometric Calculator by: Donald Scott,\nEquation Balancing by: Andrew Zeng,\nProject Leader: Aleksander Obradovic, \nTesters: Kevin Baik, Roger Liu, Aleksander Obradovic. \nAdditional credit to Jakarta Taglibs Project for data.",
                    "About",
                    JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_AboutHandle

    private void formatEquationField(JTextField field) {
        String text = field.getText();
        String[] segs;
        if (text.indexOf("+") >= 0)
            segs = text.split("\\+");
        else {
            segs = new String[1];
            segs[0] = text;
        }
        String rep = "";
        int i = 0;
        for (String seg : segs) {
            seg = seg.trim();
            char c = seg.charAt(0);
            c = Character.toUpperCase(c);
            String restOfMol = seg.substring(1, seg.length());

            seg = c + "";//Reset seg to only 1st char; rest is in restOfMol

            boolean numPrev = false;
            for (int n = 0; n < restOfMol.length(); n++) {
                String charString = restOfMol.substring(n, n + 1);
                if (numPrev)
                    seg += charString.toUpperCase();
                else
                    seg += charString;
                if (isNumber(charString))
                    numPrev = true;
                else
                    numPrev = false;
            }
            if (i != 0) {
                rep += " + " + seg;

            } else {
                rep += seg;
                i++;
            }
        }
        field.setText(rep);
    }

    private boolean isNumber(String num) {
        try {
            Integer.parseInt(num);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @param leftString  must not be null or empty
     * @param rightString must not be null or empty
     * @throws FOCException
     */
    public void setEquation(String leftString, String rightString) throws FOCException {
        if (leftString == null || leftString.length() == 0 || rightString == null || rightString.length() == 0) {
            throw new UnbalancableEquationException();
        }



        long time = System.nanoTime();
        try {
            equation = Equation.read(leftString + "=" + rightString);
            equation.balance();
            long end = System.nanoTime();

            System.out.println("Calc time: " + (end - time) / 1000000.0 + " milliseconds");
            System.out.println(equation);

        } catch (FOCException e) {
            throw e;
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
    	
        setLookandFeel();
        new MainGui().setVisible(true);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel LimitingLabel;
    private javax.swing.JScrollPane StoiCalcPane;
    private javax.swing.JPanel StoiPanel;
    private javax.swing.JPanel StoiResultsPanel;
    private javax.swing.JTextField addValField;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JList dataList;
    private gui.EquationLabel equationLabel;
    private javax.swing.JPanel equationPanel;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField leftEquationField;
    private javax.swing.JComboBox moleculeField;
    private javax.swing.JComboBox prefixBox;
    private javax.swing.JTextField rightEquationField;
    private javax.swing.JLabel statusText;
    private javax.swing.JComboBox unitBox;
    // End of variables declaration//GEN-END:variables

}
